#include "stofac.h"

#define ITERMAX 100

int main (int ac, char **av)
{
  /* First populate the problem */
  int status;
  int i,j,k;
  int flag = 0, niter=0, loopind = 1;
  double t0, t1, tbigm, tcopy;
  double objval, objvalcopy;
  int lastnode;
  
  /* Creat the data */
  int ni = atoi(av[1]);   //|I|
  int ns = atoi(av[2]);   //|W|
  double eps = 0.3;
  double x[ni];
  int *bigmrowind, *bigmcolind, *bigmchgind;

  BIGMINFO minfo;   //bigm infomation
  CONINFO  cinfo;   //continuous variables information

  /* Initialize CPLEX environment */
  CPXENVptr env = CPXopenCPLEX (&status);

  /* Creat one instance of the problem*/
  CPXLPptr lp   = CPXcreateprob (env, &status, "fac");

  /* Read paramters from .prm file */
  status = CPXreadcopyparam(env, "../param/stofac.prm");

  /* Direct output to a logfile */
  FILE* logfile = NULL;
  logfile = CPXfopen("../log/stofac.log", "w");
  status = CPXsetlogfile(env, logfile);

  /* Populate the model */
  status = DZpopulatemod(env, lp, ni, ns, eps);

  /* Clone the problem */
  CPXLPptr copy  = CPXcloneprob  (env, lp, &status);
  status = CPXwriteprob(env, copy, "loop_org.lp", NULL);
  /* Solve copied problem */
  status = CPXgettime(env, &t0);
  status = CPXmipopt(env, copy);
  status = CPXgettime(env, &t1);
  tcopy = t1 - t0;
  status  = CPXgetmipobjval (env, copy, &objvalcopy);

  /* Access big-m coeffficients and print */
  status = DZgetbigmind(env, lp, &bigmrowind, &bigmcolind, &bigmchgind);

  status = DZprintbigmval(env, lp, &bigmrowind, &bigmcolind);
  //int *conind       = (int *)malloc(ni * sizeof(int));
  //int *conchgbdsind = (int *)malloc(ni * sizeof(int));
  // to be set in the future  status = DZgetconind(env, lp, &cinfo);

  /* Install data structure to pass to the callback function */
  /* for big m*/
  minfo.ni = ni;
  minfo.ns = ns;
  minfo.flagPtr = &flag;
  minfo.bigmrowind = bigmrowind;
  minfo.bigmcolind = bigmcolind;
  minfo.bigmchgind = bigmchgind;
  minfo.nbigm = ni*ns;
  minfo.loopind = &loopind;
  minfo.lastnode = &lastnode;

  /* for continuous variables */
  cinfo.flagPtr = &flag;
  cinfo.ncon = ni;
  cinfo.conind = conind;
  cinfo.conchgbdsind = conchgbdsind;
  cinfo.loopind = &loopind;
  cinfo.lastnode = &lastnode;

  /* Set up solve callback functions for set bigms */
  status = CPXsetsolvecallbackfunc (env, DZcallbacksetbigm, &minfo);

  //status = CPXsetsolvecallbackfunc (env, DZcallbackcheckconbds, &cinfo);
  if (status) goto TERMINATE;

  /* Set initial big-m values */
  status = DZsetbigmval(env, lp, bigmrowind, bigmcolind);
  //status = DZsetconbds(env, lp, &cinfo);
  //  status = CPXwriteprob(env, lp, "loop_org.lp", NULL);
  status = CPXgettime(env, &t0);
  /* Main loop for resolving the model by updating the bigm values if checking failed*/
  while( (flag == 0) && (niter <= ITERMAX) )
    {
      printf("flag is %i and niter is %i last node is %i\n", flag, niter, lastnode);
      /* Change the bounds here */

      status = CPXmipopt(env, lp);      
      /* Change bigm values here */
      //      status = DZchgbigmval(env, lp, bigmrowind, bigmcolind, bigmchgind);
      // status = DZchgconbds(env, lp, &cinfo);

      niter++;
    }

  status = CPXgetx(env, lp, x, 0, ni-1);
  for(i = 0; i<ni; i++) printf("%f\n", x[i]);
    
  status = CPXgettime(env, &t1);
  tbigm = t1 - t0;
  status = CPXwriteprob(env, lp, "loop_mod.lp", NULL);
  status  = CPXgetmipobjval (env, lp,   &objval);

  printf("Objective by bigm  solver:    %f    Elapsed time: %f\n", objval, tbigm);
  printf("Objective by cplex solver:    %f    Elapsed time: %f\n", objvalcopy, tcopy);

  //  status = CPXwriteprob(env, lp, "stofac.lp", NULL);
  /* Change the bigM values and resolve */
  /*
  status = CPXreadcopyparam(env, "param/stofac.prm");
  status = DZchgbigmval(env, lp, bigmrowind, bigmcolind);
  //  status = DZprintbigmval(env, lp, bigmrowind, bigmcolind);
  status = CPXmipopt(env, lp);
  */

  /* Output the model */
  //  status = CPXwriteprob(env, lp, "stofac1.lp", NULL);
  //  if(status) goto TERMINATE;

 TERMINATE:
  CPXfclose(logfile);
  CPXfreeprob (env, &lp);
  CPXfreeprob (env, &copy);
  CPXcloseCPLEX (&env);

  free(bigmrowind);
  free(bigmcolind);
  free(bigmchgind);

  free(conind);
  free(conchgbdsind);

  return 0;
}
